Skip to content

VS Code for Qt Applications – Part 3 A Technical Guide

Once again, the theme of the day is how to speed up Qt development with Visual Studio Code. In part 2 of this blog series, we walked through how to get a complete setup for your qmake and CMake projects, with a deeper look at the Qt side. This time, I will share a few tips and tricks to further integrate Qt into Visual Studio Code.

In this post, we will see how to:

    • Enable syntax highlighting for Qt specific files
    • Quickly switch to Qt Creator for editing .qrc and .ui files
    • Work on single QML files by previewing them through qmlscene
    • Inspect your application with GammaRay
    • Generate profile data for your QML application

An Introduction to Code Runner

Before we start digging into new settings, it is necessary to say a few words about another Visual Studio Code extension: Code Runner. Code Runner is, in essence, an extension that lets you quickly run scripts on single files. Scripts that get run on files can be customized in the settings file. They can be associated to files through one of three mechanisms: depending on the file’s language identifier, depending on its file extension, or by matching the file name with a glob expression. The settings entries for these are, respectively: code-runner.executorMap, code-runner.executorMapByFileExtension, and code-runner.executorMapByGlob.

 

Let’s see some examples.

Matching by language id

{
    "code-runner.executorMap": {
        "cpp": "cd $dir; g++ $fileName -o $fileNameWithoutExt; ./$fileNameWithoutExt"
    }
}

This settings snippet is using script mapping by language ID. These settings will tell the Code Runner extension to launch this script for all files that are identified as C++ language files. That includes, for instance, all files with extensions .cxx, .cpp, .hxx, .hpp, .h, .cc, and so on. Furthermore, this script will be run for all the files for which the language type gets set explicitly to “C++,” either through the “Change language mode” command or through the "files.association" setting.

Matching by file extension

{
    "code-runner.executorMapByFileExtension": {
        ".cpp": "cd $dir; g++ $fileName -o $fileNameWithoutExt; ./$fileNameWithoutExt"
    }
}

This setting snippet maps the same script as before, but this time the script will only apply to files with the .cpp extension, while ignoring all the other files that get identified as C++ files by Visual Studio Code.

Matching by glob pattern

{
    "code-runner.executorMapByGlob": {
        "*.cpp": "cd $dir; g++ $fileName -o $fileNameWithoutExt; ./$fileNameWithoutExt"
   }
}

This setting snippet maps the script to all files with names matching the glob expression “*.cpp,” that is, all files with a .cpp extension that is equivalent to the last example. An advantage of using glob patterns is that you can use more complicated rules (imagine wanting a specific rule for “CMakeFiles.txt” rather than a generic script for “*.txt”). However, note that the pattern of each glob rule is matched against the file name rather than the whole relative path, so those patterns have limited scope.

As you can see from the snippets, scripts for Code Runner support variable replacement. However, variable names are custom to Code Runner, rather than the standard Visual Studio Code ones. We will be using $dir (the directory of the files on which to run the script), $fileName (the base name of the file), and $fileNameWithoutExt (the base name of the file without an extension). For all other supported variables, you can check the extension’s main page.

Once configured, the scripts mapped through Code Runner can be executed by launching the “Run Code” command or by using the key combination “Ctrl + Alt + N.”

There are few caveats to keep in mind when using Code Runner to avoid surprises.

Caveat #1: Preset configurations

There are a number of preset configurations provided by the Code Runner extension itself. You can find them here.

Furthermore, mapping from files to scripts is resolved in a specific order and, as soon as a script is found for the file, all other matching rules are ignored. The order is roughly by glob, then by language ID, then by extension. If you would like more details, you can check the source code.

Because of how mappings are resolved, it could happen that a script in your settings is not being executed as you would expect. When that happens, it’s possible that one of the default scripts is running instead. To fix that, you can override the default script by explicitly setting it to null.

For instance, let’s take the following snippet:

{
    "code-runner.executorMapByFileExtension": {
        ".cpp": "echo I am a cpp file!"
    }
}

This will not work because there is already a script mapped to the language ID, “cpp,” and that will be checked first. To get it to work as expected, you will need first to remove the default entry explicitly:

{
    "code-runner.executorMapByFileExtension": {
         ".cpp": "echo I am a cpp file!"
    },
    "code-runner.executorMap": {
         "cpp": null
    }
}

Caveat #2: Default arguments

If you don’t use any variable ($dir, $fileName, etc.) in your script, the full path to the file to run will be appended to your script implicitly.

So, if you have a rule like this one:

{
    "code-runner.executorMapByFileExtension": {
        ".cpp": "echo I am a cpp file!"
    }
}

what you will see as an output will be this:

> I am a cpp file! /full/path/to/your/cpp/file.cpp

Caveat #3: Running environment

Scripts, by default, will inherit environment variables from the Visual Studio Code process. Therefore, any command referred by scripts should be already reachable through the PATH environment variable. However, you can customize your environment from within Visual Studio Code with a few extra steps:

    1. Configure the environment for Visual Studio Code’s integrated terminal. That is done by configuring the setting "terminal.integrated.env.{windows,linux,osx}" according to your current system. For instance, in the example below, we make clang/clang++ available on the terminal under Windows.
{
    "terminal.integrated.env.windows": {
         "PATH": "${env:PATH};C:/Program Files/LLVM/bin"
    }
}
    1. Configure Code Runner so it runs its scripts on a terminal rather than using its own process. To do so, it is enough to set "code-runner.runInTerminal" to true.
{
    "code-runner.runInTerminal": true
}

Preview QML files with qmlscene

Running QML files through qmlscene only requires adding a script for QML files through Code Runner. Note that Visual Studio Code doesn’t recognize QML as a language by default. Therefore, we should either map the script by extension or by glob, or install an extension that provides QML as a language, like this one.

{
    "code-runner.executorMapByFileExtension": {
        ".qml": "qmlscene"
    }
}

If you need access to custom QML plugins that are not available in your PATH, you can change your environment through settings, making sure to have Code Runner scripts run through a terminal.

{
    "code-runner.runInTerminal": true,
    "terminal.integrated.env.windows": {
        "QML2_IMPORT_PATH": "path/to/extra/qml/plugins"
    }
}

Open qrc and ui files in Qt Creator

This snippet is useful if you want to take advantage of the Qt Creator UI for updating resource files or using the designer for .ui files. The rule for this is pretty straightforward, as what we need to do in the end is only to open a file through Qt Creator.

{
    "code-runner.executorMapByFileExtension": {
        ".qrc": "qtcreator -client",
        ".ui": "qtcreator -client"
    }
}

Note that we pass the -client argument to Qt Creator, so that we don’t end up launching a new instance every time.

Inspect your application with GammaRay

GammaRay is a powerful introspection tool for Qt applications, built by KDAB. It can attach to a running Qt application and let you do some interesting debugging with a graphical interface. Thanks to its in-depth knowledge of Qt internals, GammaRay can visualize graphically Qt Quick scene graphs, Qt Widgets hierarchies, signals, events, and so on.

If you are interested in knowing more about GammaRay, check out our tutorials on YouTube.

When launching GammaRay, we have the option to pass the path to a Qt application as an argument. If we do so, GammaRay will automatically launch the application, inject itself into it, and start the main GammaRay window. We can take advantage of this and create a launch configuration that lets us inspect our application through GammaRay in Visual Studio Code. If you don’t know how launch configurations work, you may want to read older posts of this series (Part 1, Part 2).

{
    "name": "Launch app with GammaRay",
    "type": "cppvsdbg",
    "request": "launch",
    "program": "GammaRay",
    "args": ["path/to/our/app", "appArg1", "appArg2", ...],
    "console": "internalConsole",
     "cwd": "${workspaceFolder}"
}

Note that this launch configuration requires that you have GammaRay in your path.

Additionally, if the project is using CMake and is built through the Visual Studio Code CMake extension, we can also tune the GammaRay launch configuration so it runs the active CMake target through GammaRay, by slightly changing the args parameter of the configuration, as shown below.

{
    "name": "Launch current CMake target with GammaRay",
    "type": "cppvsdbg",
    "request": "launch",
    "program": "GammaRay",
    "args": ["${command:cmake.launchTargetPath}"],
    "console": "internalConsole",
    "cwd": "${workspaceFolder}"
}

Profile QML applications with qmlprofiler

You can generate profile data for your QML application directly from Visual Studio Code by using qmlprofiler. To add that to your Visual Studio Code project it’s enough to add a launch configuration as follows:

{
    "name": "Profile application with qmlprofile",
    "type": "cppvsdbg",
    "request": "launch",
    "program": "qmlprofiler",
    "args": ["-o", "your/favourite/output/dir/qmlprofiler.qtd", "path/to/your/app"],
}

Alternatively, to launch the current CMake target instead of a fixed executable, we can write a configuration like this:

{
    "name": "Profile current CMake target with qmlprofile",
    "type": "cppvsdbg",
    "request": "launch",
    "program": "qmlprofiler",
    "args": ["-o", "your/favourite/output/dir/qmlprofiler.qtd", "${command:cmake.launchTargetPath}"],
}

The output .qtd file can then be loaded by Qt Creator’s QML Profiler.

Syntax highlighting

There are a few file types that recur often in Qt projects.

When developing a Qt application, you may get to manipulate files with nonstandard extensions, such as resource files (.qrc), ui definition files (.ui), or moc files (.moc).

By default, Visual Studio Code will not be able to infer the file type for those files whose extensions it doesn’t know. It will then default the file type to “Plain Text,” which also means there will be no code highlighting.

Visual Studio Code will let you customize the file associations for files by using a glob pattern. You can take advantage of that and get Qt specific files to look as you would expect. To create new code highlight associations, it is enough to update the "files.association" setting in your settings.

For our case in particular, with Qt, the specific files extensions “.moc”, “.qrc” and “.ui” are enough to add the following lines in your workspace settings:

{
    "files.associations": {
        "*.moc": "cpp",
        "*.qrc": "xml",
        "*.ui": "xml"
    }
}

If you think those rules will not clash, you can choose to apply them across workspaces. There are two options to do so:

  1. At a global level, by calling the “Preferences: Open Default Settings (JSON)” command and updating "files.associations" there, or
  2. At the user level, by calling “Preferences: Open Settings (JSON)” command and updating "files.associations".

There is also a GUI option to change files associations, which can be used only to update user settings.

Thank you for reading.

I hope you’ve enjoyed this blog series and that it helps improve your productivity.

If you are interested in Visual Studio Code, you may also like Using Visual Studio Code for Writing Qt Applications and Improving C++ Development in Visual Studio Code with compile_commands.json and Bear.

About KDAB

If you like this article and want to read similar material, consider subscribing via our RSS feed.

Subscribe to KDAB TV for similar informative short video content.

KDAB provides market leading software consulting and development services and training in Qt, C++ and 3D/OpenGL. Contact us.

Leave a Reply

Your email address will not be published. Required fields are marked *